var EXPORTED_SYMBOLS = ['g_SyncGoogle'];

const Cc = Components.classes;
const Ci = Components.interfaces;

Components.utils.import("resource://gsync/utils.js");

/**
 * Google Bookmark specific services
 */
var g_SyncGoogle = {

    signature: null,
    
    deleteSignature: null,
    
    ////////////////////////////////////////
    /// Bookmark provider interface
    ////////////////////////////////////////
    
    doInSecurityContext: function(credentials, callback){
    
        //TODO try/catch and rethrow any error...
        
        var alreadyLoggedIn = this.isLoggedIn();
        
        if (!alreadyLoggedIn && credentials.login) {
            this.login(credentials.username, credentials.password);
        }
        
        callback.call(this);
        
        //if (!alreadyLoggedIn && credentials.login) {
        this.logout();
        //}
    },
    
    insertBookmarks: function(bookmarks){
    
        LOG.trace("g_SyncGoogle#insertBookmarks BEGIN");
        
        //TODO errorhandling and progess
        for (idx in bookmarks) {
            LOG.trace("g_SyncGoogle#insertBookmarks inserting " + bookmarks[idx]);
            this.updateBookmark(bookmarks[idx]);
        }
    },
    
    deleteAllBookmarks: function(){
    
        LOG.trace("g_SyncGoogle#deleteAllBookmarks() BEGIN");
        
        var url = this.getPref("deleteUrl"); //'https://www.google.com/bookmarks/delete?ceh=1';
        var query = "&prev=" + encodeURIComponent("/lookup");
        query += '&sig=' + this.getDeleteSignature();
        
        GSYNC_UTILS.doInRequest(url, query, "POST", false, function(){
            LOG.debug("g_SyncGoogle#deleteAllBookmarks() SUCCESS");
        }, this);
    },
    
    
    getAllBookmarks: function(){
    
        LOG.trace("g_SyncGoogle#getAllBookmarks() BEGIN");
        
        var result = [];
        
        var url = this.getPref("rssUrl"); //"https://www.google.com/bookmarks/lookup?output=rss&num=100000";
        GSYNC_UTILS.doInRequest(url, null, "GET", false, function(request){
        
            LOG.debug("g_SyncGoogle#getAllBookmarks() Got response");
            var document = request.responseXML;
            
            //TODO Optimize and simplify e.g. refactor
            
            getNodeValue = function(element, tagName, namespace){
            
                var result = "";
                var nodeList = element.getElementsByTagName(tagName);
                if (nodeList && (nodeList.length > 0)) {
                    if (nodeList[0].firstChild) {
                        result = nodeList[0].firstChild.nodeValue;
                    }
                }
                return result;
            }
            
            getNodeValues = function(element, tagName, namespace){
            
                var result = [];
                var nodeList = element.getElementsByTagName(tagName);
                if (nodeList && (nodeList.length > 0)) {
                    for (var k = 0; k < nodeList.length; k++) {
                        if (nodeList[k].firstChild) {
                            result.push(nodeList[k].firstChild.nodeValue);
                        }
                    }
                }
                return result;
            }
            
            if (this.signature == null) {
                this.signature = this.extractSignature(document);
            }
            
            var items = document.documentElement.getElementsByTagName("item");
            for (var i = 0; i < items.length; i++) {
            
                var labels = getNodeValues(items[i], "smh:bkmk_label");
                if (labels.length == 0) {
                    var bookmark = new Bookmark();
                    bookmark.title = getNodeValue(items[i], "title");
                    bookmark.link = getNodeValue(items[i], "link");
                    bookmark.date = getNodeValue(items[i], "pubDate");
                    bookmark.description = getNodeValue(items[i], "description");
                    bookmark.id = getNodeValue(items[i], "smh:bkmk_id");
                    result.push(bookmark);
                    LOG.trace("g_SyncGoogle#getAllBookmarks() recived:" + bookmark);
                } else {
                    for (var label in labels) {
                        var bookmark = new Bookmark();
                        bookmark.label = labels[label];
                        bookmark.title = getNodeValue(items[i], "title");
                        bookmark.link = getNodeValue(items[i], "link");
                        bookmark.date = getNodeValue(items[i], "pubDate");
                        bookmark.description = getNodeValue(items[i], "description");
                        bookmark.id = getNodeValue(items[i], "smh:bkmk_id");
                        result.push(bookmark);
                        LOG.trace("g_SyncGoogle#getAllBookmarks() recived:" + bookmark);
                    }
                }
            }
        }, this);
        
        LOG.debug("g_SyncGoogle#getAllBookmarks() count:" + result.length);
        return result;
    },
    
    getSignature: function(){
    
        LOG.trace("g_SyncGoogle#getSignature BEGIN");
        
        if (this.signature == null) {
            var url = this.getPref("rssUrl"); //"https://www.google.com/bookmarks/lookup?output=rss&num=100000";
            GSYNC_UTILS.doInRequest(url, null, "GET", false, function(request){
                var document = request.responseXML;
                this.signature = this.extractSignature(document);
                LOG.debug("g_SyncGoogle#getSignature signature" + this.signature);
            }, this);
        }
        return this.signature;
    },
    
    getDeleteSignature: function(){
    
        if (this.deleteSignature != null) {
            return this.deleteSignature;
        }
        
        var url = this.getPref("deleteSigUrl"); // 'http://www.google.com/bookmarks/edit?ceh=1';
        return GSYNC_UTILS.doInRequest(url, null, "GET", false, function(request){
        
            const signaturePosition = 'name="sig" value="';
            var response = request.responseText;
            
            var begin = response.indexOf(signaturePosition) + signaturePosition.length;
            var end = response.indexOf('"', begin + 1);
            var signature = response.substring(begin, end);
            LOG.debug("g_SyncGoogle#getDeleteSignature() signature:" + signature);
            this.deleteSignature = signature;
            return signature;
            
        }, this);
    },
    
    extractSignature: function(document){
    
        LOG.trace("g_SyncGoogle#extractSignature() BEGIN");
        var result = null;
        var signatureElement = document.documentElement.getElementsByTagName("smh:signature");
        if (signatureElement.length > 0) {
            result = signatureElement[0].firstChild.nodeValue;
        } else {
            result = null;
        }
        LOG.debug("g_SyncGoogle#extractSignature() signature:" + result);
        return result;
    },
    
    isLoggedIn: function(){
    
        LOG.trace("g_SyncGoogle#isLoggedIn() BEGIN");
        
        var cookieManager = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
        var iterator = cookieManager.enumerator;
        
        var result = false;
        while (iterator.hasMoreElements()) {
            var cookie = iterator.getNext();
            if (cookie instanceof Components.interfaces.nsICookie) {
                if (cookie.host == ".google.com") 
                    if (cookie.name == "SID") {
                        result = true;
                        break;
                    }
            }
        }
        LOG.debug("g_SyncGoogle#isLoggedIn() cookie:" + result);
        return result;
    },
    
    logout: function(){
    
        LOG.trace("g_SyncGoogle#logout() BEGIN");
        
        var url = this.getPref("logoutUrl"); // https://www.google.com/accounts/Logout2;
        GSYNC_UTILS.doInRequest(url, null, "GET", false, function(){
            LOG.debug("g_SyncGoogle#logout() SUCCESS");
        }, this);
    },
    
    login: function(username, password){
    
        LOG.trace("g_SyncGoogle#login() BEGIN");
        
        var url = this.getPref("loginUrl"); //https://www.google.com/accounts/ServiceLoginAuth
        var query = "ltmpl=wsad&ltmplcache=2&rm=false&Email=" + username + "&Passwd=" + password;
        
        GSYNC_UTILS.doInRequest(url, query, "POST", false, function(){
            var success = this.isLoggedIn();
            LOG.debug("g_SyncGoogle#login() success:" + success);
        }, this);
    },
    
    updateBookmark: function(bookmark){
    
        LOG.trace("g_SyncGoogle#updateBookmark BEGIN");
        
        var url = this.getPref("updateUrl"); //https://www.google.com/bookmarks/mark
        var queryString = '&bkmk=' + encodeURIComponent(bookmark.link);
        queryString += '&title=' + encodeURIComponent(bookmark.title);
        queryString += '&labels=' + encodeURIComponent(bookmark.label)
        // TODO annotation/description
        queryString += '&annotation=';
        queryString += "&zx=" + Math.floor(Math.random() * 32768);
        queryString += '&sig=' + this.getSignature();
        
        GSYNC_UTILS.doInRequest(url, queryString, "POST", false, function(){
            LOG.trace("g_SyncGoogle#updateBookmark SUCCESS");
        }, this);
    },
    
    getPref: function(name){
    
        var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
        return prefs.getBranch("extensions.gsync.googglebookmarks.").getCharPref(name);
        
    }
}
